package ad_exercise_4.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * This class contains the main method which does some compressing and decompressing using two different implementations of the LZW compression algorithm and measures the time it takes
 * 
 * @author Sjaak Smetsers (number?)
 * @author Karen Berntsen (s0815799)
 * @author Erik Stens (s0615374)
 */
public class AD_exercise_4 {
	public static void main(String[] args) {
		long now;
		
		now = System.currentTimeMillis();
		mainNaive("./resources/abacababa.txt");
		mainNaive("./resources/aaaaaaaaaaa.txt");
		mainNaive("./resources/LZWTree.java");
		mainNaive("./resources/waffles.bmp");
		System.out.println("The elapsed time for compressing 4 files using the naive LZW implementation is " + (System.currentTimeMillis() - now) + " milliseconds\n");
		
		now = System.currentTimeMillis();
		mainLZWTree("./resources/", "abacababa.txt", "abacababa.zip");
		mainLZWTree("./resources/", "aaaaaaaaaaa.txt", "aaaaaaaaaaa.zip");
		mainLZWTree("./resources/", "LZWTree.java", "LZWTree.zip");
		mainLZWTree("./resources/", "waffles.bmp", "waffles.zip");
		System.out.println("The elapsed time for compressing 4 files using the tree-based LZW implementation is " + (System.currentTimeMillis() - now) + " milliseconds\n");
		
		now = System.currentTimeMillis();
		mainDecompress("./resources/", "abacababa.zip", "abacababa - decompressed.txt");
		mainDecompress("./resources/", "aaaaaaaaaaa.zip", "aaaaaaaaaaa - decompressed.txt");
		mainDecompress("./resources/", "LZWTree.zip", "LZWTree - decompressed.java");
		mainDecompress("./resources/", "waffles.zip", "waffles - decompressed.bmp");
		System.out.println("The elapsed time for decompressing 4 LZW compressed files is " + (System.currentTimeMillis() - now) + " milliseconds\n");
	}
	
	/**
	 * Method for compressing inputFile using the naive LZW compression implementation. Doesn't output to a file, just for debugging the tree implementation and for speed comparison.
	 * 
	 * @param inputFile
	 */
	private static void mainNaive(String inputFile) {
		try {
			BufferedInputStream input = new BufferedInputStream(new FileInputStream(new File(inputFile)));
			LZWNaive lzwNaive = new LZWNaive();
			lzwNaive.compress(input);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Method for printing the bytes in a file as numbers, for debug purposes
	 * 
	 * @param inputFile
	 */
	private static void printFile(String inputFile) {
		try {
			BufferedInputStream input = new BufferedInputStream(new FileInputStream(new File(inputFile)));
			LZWUtil.printBytes(input);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Method for compressing inputFile using an implementation if the LZW compression algorithm that uses a prefix tree that represents the codetable. Outputs to outputFile.
	 * 
	 * @param dir
	 *            base directory where the inputFile resides and where the outputFile should be written to
	 * @param inputFile
	 * @param outputFile
	 */
	private static void mainLZWTree(String dir, String inputFile, String outputFile) {
		System.out.println("Compressing '" + dir + inputFile + "'");
		try {
			BufferedInputStream input = new BufferedInputStream(new FileInputStream(new File(dir + inputFile)));
			BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(new File(dir + outputFile)));
			LZWUtil.compress(input, output);
			System.out.println("Finished compression of '" + dir + inputFile + "'\n");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Method for decompressing an LZW compressed file.
	 * 
	 * @param dir
	 *            base directory where the inputFile resides and where the outputFile should be written to
	 * @param inputFile
	 * @param outputFile
	 */
	private static void mainDecompress(String dir, String inputFile, String outputFile) {
		System.out.println("Decompressing '" + dir + inputFile + "'");
		try {
			BufferedInputStream input = new BufferedInputStream(new FileInputStream(new File(dir + inputFile)));
			BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(new File(dir + outputFile)));
			LZWUtil.decompress(input, output);
			System.out.println("Finished decompression of '" + dir + inputFile + "'\n");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
